VOID Render(D3DXVECTOR3 * pvOffSet,DWORD dwPhase,IDirect3DDevice9 *pDevice,DWORD dwColor)
{
     BOOL bSuccess = false;
            
    //if you have not yet timed a draw do so now.
    if(g_bCheckDrawTime && g_lFrequency.QuadPart > 0)
    {
        bSuccess = QueryPerformanceCounter( &g_StartPerformanceCount );
    }

    CPUActive();
    // Setup the world, view, and projection matrices
    SetupMatrices(pvOffSet,dwPhase,pDevice);

    // Setup our texture. Using Textures introduces the texture stage states,
    // which govern how Textures get blended together (in the case of multiple
    // Textures) and lighting information. In this case, we are modulating
    // (blending) our texture with the diffuse color of the vertices.
    pDevice->SetRenderState(D3DRS_TEXTUREFACTOR,dwColor);
    pDevice->SetTexture( 0, g_pTexture );
    pDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
    pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
    pDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_MODULATE );
    pDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TFACTOR );
    pDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
    pDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
    // Render the vertex buffer contents
    pDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
    pDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
    pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 );
    
    if(g_bCheckDrawTime && bSuccess)
    {

        if(QueryPerformanceCounter( &g_EndPerformanceCount ))
        {
            LARGE_INTEGER time;
            time.QuadPart = (g_EndPerformanceCount.QuadPart - g_StartPerformanceCount.QuadPart);
            LONGLONG dtime = g_lFrequency.QuadPart / 1000000 ;
            __int64 mseconds = time.QuadPart/dtime;
            g_fDrawCost = mseconds;
        }
    }
    if(g_bCheckDrawTime)
        g_bCheckDrawTime = false;


}

VOID Render(DWORD nParam,IDirect3DDevice9 *pDevice,bool bMultiThread)
{

    D3DXVECTOR3 vTemp; 
    vTemp.z = float( g_dwNumberofObjectsSqrt * 8 );
    
    for(int i = 0; i< g_dwNumberofObjectsSqrt; i++ )
    {
        if(!g_bMultiThread || i % g_dwNumberofRecordThreads == nParam )
        {
            for(int j = 0; j< g_dwNumberofObjectsSqrt; j++)
            {

                    vTemp.x = float( 4*i - 2*g_dwNumberofObjectsSqrt );
                    vTemp.y = float( 4*j - 2*g_dwNumberofObjectsSqrt );
                    Render(&vTemp, i*j*100 ,pDevice,g_dwColors[(nParam%g_dwNumberofColors)]);
               
            }
        }
    }         
}

DWORD WINAPI RenderThreadProc(LPVOID pParam)
{
    DWORD nParam = (DWORD) pParam;
    while(true)
    {
        WaitForSingleObject(g_RenderRecordSem[nParam], INFINITE);
        //figure out what buffer to use.
        DWORD nBuffer = nParam + g_dwNumberofRecordThreads*g_dwCurrentBufferSet;
        //don't start recording until everything is ready.
        if(g_DoRender)
        {
            //record your objects assigned to this thread.
            g_bCBValid[nBuffer] = true;

            g_pCBRecorder[nBuffer]->BeginCommandBuffer();
            Render(nParam,g_pCBRecorder[nBuffer],true);
            g_pCBRecorder[nBuffer]->EndCommandBuffer();

#if DOTRACE
            char temp[300];
            sprintf_s(temp,299,"recording on thread %d, Buffer %d, Bufferset %d, after frame %d present.\n",nParam,nBuffer,g_dwCurrentBufferSet,g_dwFrame);
            OutputDebugStringA(temp);
#endif
        }
        //finished with this recording.
        ReleaseSemaphore(g_RenderPlaybackSem[nParam], 1, NULL);
    }
    return 0;
}
